package com.fdb.efp.console.api.rest;

import com.alibaba.fastjson.JSON;
import com.fdb.basic.framework.core.constant.ApplicationConstance;
import com.fdb.basic.framework.core.constant.ResponseData;
import com.fdb.basic.framework.core.util.StringUtil;
import com.fdb.basic.framework.core.util.TimeUtil;
import com.fdb.basic.framework.core.util.ValidationUtils;
import com.fdb.basic.framework.web.controller.AbstractController;
import com.fdb.efp.console.service.facade.SUserService;
import com.fdb.efp.console.api.service.CusToolService;
import com.fdb.efp.console.service.facade.PersonalWhiteListService;
import com.fdb.efp.console.service.vo.PersonalWhiteDeleteExcelVO;
import com.fdb.efp.console.service.vo.PersonalWhiteExcelVO;
import com.fdb.efp.console.service.vo.PersonalWhiteListVO;
import com.fdb.efp.console.common.ExcelException;
import com.fdb.efp.console.common.util.ExcelImportCusUtil;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.Charset;
import java.util.*;
import java.util.stream.Collectors;


@RestController
@RequestMapping("/api")
public class PersonalWhiteListController extends AbstractController {

	@Autowired
	@Qualifier("personalWhiteListService")
	private PersonalWhiteListService personalWhiteListService;

	@Autowired
	@Qualifier("sUserService")
	private SUserService sUserService;

	@Autowired
	@Qualifier("cusToolService")
	private CusToolService cusToolService;

	private List<PersonalWhiteExcelVO> errorHisDuplicateDataList = new ArrayList<>();
	private List<PersonalWhiteExcelVO> singleRowList = new ArrayList<>();

	private List<PersonalWhiteDeleteExcelVO> errorHisDuplicateDataListD = new ArrayList<>();
	private List<PersonalWhiteDeleteExcelVO> singleRowListD = new ArrayList<>();

	private static Logger logger = LoggerFactory.getLogger(PersonalWhiteListController.class);

	private static final String CONTENTTYPE = "application/json;charset=UTF-8";

	private static final String MODELNAME = "个人白名单更新模板.xls";

	private static final String SHEET1NAME = "个人白名单上传";

	private static final String IMPORT_PATH = "/template/perlWhUpList.xls";

	private static final String MODELNAME1 = "个人白名单删除模板.xls";

	private static final String SHEET1NAME1 = "个人白名单删除";

	private static final String IMPORT_PATH1 = "/template/perlWhDeList.xls";

	/**
	 * 列表数据查询
	 * @return
	 */
	@RequestMapping(value="/personal/white/lists", method= RequestMethod.POST)
	public @ResponseBody
	ResponseData<List<PersonalWhiteListVO>> queryPersonalWhiteListAll(@RequestBody PersonalWhiteListVO vo) {
		List<PersonalWhiteListVO> outputVo = personalWhiteListService.queryAllList(vo);

		cusToolService.displayOrgName(outputVo,"appearOrg","appearName");

		return getResponseData(outputVo);

	}

	@RequestMapping(value = "/query/personal/effectiveDate", method = RequestMethod.POST)
	public @ResponseBody ResponseData<Integer> queryEffectiveDt() {
		int outputVo = personalWhiteListService.effectiveDate();
		return getResponseData(outputVo);
	}

	/**
	 * 根据主键查询详情
	 * @return
	 */
	@RequestMapping(value="/personal/white/list", method=RequestMethod.GET)
	public @ResponseBody
	ResponseData<PersonalWhiteListVO> queryByPk() {
		PersonalWhiteListVO inVo = new PersonalWhiteListVO();
		PersonalWhiteListVO outputVo = personalWhiteListService.queryByPk(inVo);
		return getResponseData(outputVo);

	}

	/**
	 * 根据身份证号批量删除信息
	 *
	 * @param personalWhiteListVO
	 * @return
	 */
	@RequestMapping(value = "/personal/white/list/delete", method = RequestMethod.DELETE)
	public @ResponseBody ResponseData<Integer> batchDeleteByCode(@RequestBody PersonalWhiteListVO personalWhiteListVO) {
		int outputVo = personalWhiteListService.batchDeleteByCode(personalWhiteListVO);
		return getResponseData(outputVo);
	}

	/**
	 * 设置有效日期
	 * @return
	 */
	@RequestMapping(value = "/personal/white/setDt", method = RequestMethod.PUT)
	public @ResponseBody ResponseData<Integer> setEffDtById(@RequestBody PersonalWhiteListVO personalWhiteListVO) {

		int outputVo = personalWhiteListService.upDateToSetDt(personalWhiteListVO);
		return getResponseData(outputVo);

	}


	/**
	 * 下载导入更新模板
	 * @return
	 */
	@RequestMapping(value="/personal/white/up/downLoad", method=RequestMethod.GET)
	public @ResponseBody ResponseData<String> pWUDownLoad(HttpServletResponse response, HttpServletRequest request) throws IOException {
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			response.setContentType(CONTENTTYPE);
			/**
			 * getBytes()，需要声明一下读取的编码方式，不然IE浏览器，会出现文件名乱码，谷歌不会
			 * 【解决方法】 getBytes("GBK")
			 */
			response.setHeader("Content-Disposition", "attachment;filename="+  new String((MODELNAME).getBytes("GBK"), "ISO8859-1"));
			ServletOutputStream out = response.getOutputStream();
			logger.info("下载白名单上传更新模板开始----------------------------");
			bis = new BufferedInputStream(PersonalWhiteListController.class.getClassLoader().getResourceAsStream(IMPORT_PATH));
			bos = new BufferedOutputStream(out);
			byte[] buff = new byte[2048];
			int bytesRead;
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
		} catch (Exception e) {
			logger.error("白名单上传更新模板下载失败：" , e);
			return getResponseData(null);
		} finally {
			if(null != bis) {
				bis.close();
			}
			if(null != bos){
				bos.close();
			}
		}
		logger.info("下载白名单上传更新模板结束。。。。。。。。。。。。。。。。。。。");
		return getResponseData("success!");
	}

	/**
	 * 下载导入删除模板
	 * @return
	 */
	@RequestMapping(value="/personal/white/delete/downLoad", method=RequestMethod.GET)
	public @ResponseBody ResponseData<String> dWUDownLoad(HttpServletResponse response, HttpServletRequest request) throws IOException {
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			response.setContentType(CONTENTTYPE);
			/**
			 * getBytes()，需要声明一下读取的编码方式，不然IE浏览器，会出现文件名乱码，谷歌不会
			 * 【解决方法】 getBytes("GBK")
			 */
			response.setHeader("Content-Disposition", "attachment;filename="+  new String((MODELNAME1).getBytes("GBK"), "ISO8859-1"));
			ServletOutputStream out = response.getOutputStream();
			logger.info("下载白名单删除模板开始----------------------------");
			bis = new BufferedInputStream(PersonalWhiteListController.class.getClassLoader().getResourceAsStream(IMPORT_PATH1));
			bos = new BufferedOutputStream(out);
			byte[] buff = new byte[2048];
			int bytesRead;
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
		} catch (Exception e) {
			logger.error("白名单删除模板下载失败：" , e);
			return getResponseData(null);
		} finally {
			if(null != bis) {
				bis.close();
			}
			if(null != bos){
				bos.close();
			}
		}
		logger.info("下载白名单删除模板结束。。。。。。。。。。。。。。。。。。。");
		return getResponseData("success!");
	}

	/****************************************导入删除开始**************************************************/
	/**
	 * 导入删除文件
	 */
	@SuppressWarnings("resource")
	@RequestMapping(value="/personal/white/import/delete", method=RequestMethod.POST)
	public void  personalWhiteListDelete(HttpServletResponse respone, HttpServletRequest request) {
		ResponseData<List<PersonalWhiteListVO>> result = new ResponseData<List<PersonalWhiteListVO>>();
		List<File> personalWhiteList = new ArrayList<File>();
		respone.setContentType(CONTENTTYPE);
		OutputStream out = null;
		String errorLoanUnpdPriMsg = "";
		int errorRow = 4;
		Map<Integer, String> errorList = new HashMap<Integer, String>();

		String rs = "";
		try {
			out = respone.getOutputStream();
			//获取文件
			personalWhiteList = getFileList(request);
			if(!personalWhiteList.isEmpty()){
				for(File file : personalWhiteList){
					/**
					 * 将Excel文件解析成对应实体Bean
					 */
					List<PersonalWhiteDeleteExcelVO> personalWhiteDelExcList = ExcelImportCusUtil.importExcelByClass(SHEET1NAME1, file, PersonalWhiteDeleteExcelVO.class);
					//批量删除数据
					if(personalWhiteDelExcList.size() > 0 ){
						for(PersonalWhiteDeleteExcelVO item : personalWhiteDelExcList){
							PersonalWhiteListVO param = new PersonalWhiteListVO();
							param.setCertCode(item.getCertCode());
							List<PersonalWhiteListVO> queryRs = personalWhiteListService.queryConditions(param);
							if(Objects.isNull(queryRs)) {
								errorLoanUnpdPriMsg = "导入的Excel文档第【" + errorRow + "】行数据证件号码不存在";
								logger.info("数据错误：" + errorLoanUnpdPriMsg);
								collError(errorList,errorRow,errorLoanUnpdPriMsg);
							}
							errorRow++;
						}

						rs += sortAndSpliceMap(errorList);

						personalWhiteListService.batchDelPersnalWhiteByExcel(personalWhiteDelExcList);

						List<PersonalWhiteListVO> deleteListBatch = new ArrayList<PersonalWhiteListVO>();
						deleteListBatch =  assembleDelteData(singleRowListD);

						//错误信息
						if (!StringUtil.isNullorBank(rs)) {
							rs = "ExcelError:" + rs;
							throw new Exception(rs);
						}

						result = getResponseData(deleteListBatch);

					}else{
						result = result.createData(null, ApplicationConstance.FAILURE, "文件内容为空", false);
					}
				}

			}else{
				throw new ExcelException("获取不到上传的文件！");
			}
		} catch (Exception e) {
			logger.error("文件上传失败,失败原因:", e);
			result = result.createData(null, ApplicationConstance.FAILURE, e.getMessage(), false);
		} finally {
			String str = JSON.toJSONString(result);
			try {
				out.write(str.getBytes(Charset.forName("UTF-8")));
				out.flush();
				out.close();
			} catch (IOException e) {
				logger.error("关闭数据流OutputStream出错，错误信息为：", e);
			}
		}
	}
	private List<PersonalWhiteListVO> assembleDelteData(List<PersonalWhiteDeleteExcelVO> personalWhiteDelExcelVO) throws Exception {
		List<PersonalWhiteListVO> list = new ArrayList<>();
		if (Objects.nonNull(personalWhiteDelExcelVO)) {
			Iterator<PersonalWhiteDeleteExcelVO> iterator = personalWhiteDelExcelVO.iterator();
			while(iterator.hasNext()) {
				PersonalWhiteDeleteExcelVO tempExcelVO = iterator.next();
				PersonalWhiteListVO personalWhiteListVO = new PersonalWhiteListVO();
				//设置姓名
				personalWhiteListVO.setCusName(tempExcelVO.getCusName());
				//设置证件号码
				personalWhiteListVO.setCertCode(tempExcelVO.getCertCode());
				list.add(personalWhiteListVO);
			}
		} else {
			throw new ExcelException("获取数据为空!");
		}
		return list;
	}
	/****************************************导入删除结束**************************************************/

	/****************************************导入更新开始**************************************************/
	/**
	 * 导入更新文件
	 */
	@SuppressWarnings("resource")
	@RequestMapping(value="/personal/white/list/upload", method=RequestMethod.POST)
	public void  personalWhiteListUpload(HttpServletResponse respone, HttpServletRequest request) {
		ResponseData<List<PersonalWhiteListVO>> result = new ResponseData<List<PersonalWhiteListVO>>();
		List<File> personalWhiteList = new ArrayList<File>();
		respone.setContentType(CONTENTTYPE);
		OutputStream out = null;
		int total = 0;
		int illegal = 0;
		int repeatNum = 0;
		try {
			out = respone.getOutputStream();
			//获取文件
			personalWhiteList = getFileList(request);
			if(!personalWhiteList.isEmpty()){
				for(File file : personalWhiteList){
					/**
					 * 将Excel文件解析成对应实体Bean
					 */
					List<PersonalWhiteExcelVO> personalWhiteExcList = ExcelImportCusUtil.importExcelByClass(SHEET1NAME, file, PersonalWhiteExcelVO.class);

					if(personalWhiteExcList.size()>0){
						//检查历史数据是否重复
						String errStr = "";
						errStr = checkHisDatas(personalWhiteExcList);
						//组装数据
						List<PersonalWhiteListVO> insertListBatch = new ArrayList<PersonalWhiteListVO>();
						insertListBatch =  assembleData(singleRowList);
						//批量插入
						//执行插入操作
						int num = 0;
						if (insertListBatch.size() > 0) num = execBatchInsertSql(insertListBatch);
						if (num < 0) throw new Exception("插入数据出错！");
						//错误信息
						if (!StringUtil.isNullorBank(errStr)) {
							errStr = "ExcelError:" + errStr;
							throw new Exception(errStr);
						}
						//组装结果
						result = getResponseData(insertListBatch);
					}else{
						result = result.createData(null, ApplicationConstance.FAILURE, "文件内容为空", false);
					}
				}
			}else{
				throw new ExcelException("获取不到上传的文件！");
			}
		} catch (Exception e) {
			logger.error("文件上传失败,失败原因:", e);
			result = result.createData(null, ApplicationConstance.FAILURE, e.getMessage(), false);
		} finally {
			String str = JSON.toJSONString(result);
			try {
				out.write(str.getBytes(Charset.forName("UTF-8")));
				out.flush();
				out.close();
			} catch (IOException e) {
				logger.error("关闭数据流OutputStream出错，错误信息为：", e);
			}
		}
	}

	private String checkHisDatas(List<PersonalWhiteExcelVO> checkExcelVOList) throws Exception {
		int errorRow = 4;
		List<Integer> errorDuplicateRowList = new ArrayList<>();
		String errorDuplicateMsg = "";
		errorHisDuplicateDataList.clear();
		Map<Integer, String> errorList = new HashMap<Integer, String>();

		String errorLoanUnpdPriMsg = "";

		for (PersonalWhiteExcelVO item : checkExcelVOList) {
			if ("".equals(item.getCertCode()) || item.getCertCode()==null || !ValidationUtils.idCardValidate(item.getCertCode())){
				errorLoanUnpdPriMsg = "导入的Excel文档第【" + errorRow + "】行数据证件号码格式错误";
				logger.info("数据错误：" + errorLoanUnpdPriMsg);
				collError(errorList,errorRow,errorLoanUnpdPriMsg);
				errorHisDuplicateDataList.add(item);

			}else {
				boolean flag = checkDataIsUnique(item);
				if (flag) {
					errorHisDuplicateDataList.add(item);

					//数据存在则更新
					updatePersonalWhite(item);
				}
			}
			errorRow++;
		}

		//收集没问题的导入数据
		singleRowList.clear();
		singleRowList = checkExcelVOList.stream().filter(a->!errorHisDuplicateDataList.contains(a)).collect(Collectors.toList());

		//按key值对errorList排序并将value拼接成字符串
		String rs = "";
		rs += sortAndSpliceMap(errorList);
		return rs;
	}

	/**
	 * 查询数据是否存在
	 */
	private boolean checkDataIsUnique(PersonalWhiteExcelVO item) throws Exception {
		PersonalWhiteListVO param = new PersonalWhiteListVO();
		param.setCertCode(item.getCertCode());
		List<PersonalWhiteListVO> queryRs = personalWhiteListService.queryConditions(param);
		return  Objects.isNull(queryRs) ? false : true;
	}

	/**
	 * 存在则更新该条记录
	 */
	private int updatePersonalWhite(PersonalWhiteExcelVO personalExcel) {
		int num = 0;
		PersonalWhiteListVO updatePersonal = new PersonalWhiteListVO();
		updatePersonal.setCusName(personalExcel.getCusName());
		updatePersonal.setCertCode(personalExcel.getCertCode());
		updatePersonal.setSalary(personalExcel.getSalary());
		updatePersonal.setCompanyName(personalExcel.getCompanyName());
		updatePersonal.setCompanyCity(personalExcel.getCompanyCity());
		updatePersonal.setPositionPost(personalExcel.getPositionPost());
		updatePersonal.setAppearOrg(personalExcel.getAppearOrg());

        setUserInfoToVO(personalExcel);
        String currDt = TimeUtil.getCurrentDateTime();
        String currDt1 = currDt.substring(0,10);
        String currDt2 = currDt.substring(11);

        String userId = personalExcel.getLoginUserId();
		String userName = queryUserName(userId);

        //最后更新日期
        updatePersonal.setUpdateDate(currDt1);
        //最后更新时间
        updatePersonal.setUpdateTime(currDt2);
        //最后更新人员
        updatePersonal.setUpdateNo(userId);
        //最后更新人员名称
		updatePersonal.setUpdateName(userName);

		return num = personalWhiteListService.updatePersonal(updatePersonal);
	}

	@SuppressWarnings("rawtypes")
	private List<File> getFileList(HttpServletRequest request) throws IOException{
		List<File> listFiles = new ArrayList<File>();
		CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
		if(multipartResolver.isMultipart(request)){
			MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
			Iterator iter = multiRequest.getFileNames();
			while(iter.hasNext()) {
				MultipartFile mFile = multiRequest.getFile(iter.next().toString());
				if(mFile != null){
					listFiles.add(multipartToFile(mFile));
				}
			}
		}
		return listFiles;
	}

	private File multipartToFile(MultipartFile multfile) throws IOException {
		CommonsMultipartFile cmf = (CommonsMultipartFile)multfile;
		DiskFileItem dfi = (DiskFileItem) cmf.getFileItem();
		File file = dfi.getStoreLocation();
		if(file.length() < 2048){
			File tmpFile = new File(System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") +  file.getName());
			multfile.transferTo(tmpFile);
			return tmpFile;
		}
		return file;
	}

	private List<PersonalWhiteListVO> assembleData(List<PersonalWhiteExcelVO> personalWhiteExcelVO) throws Exception {
		List<PersonalWhiteListVO> list = new ArrayList<>();
		if (Objects.nonNull(personalWhiteExcelVO)) {
            PersonalWhiteListVO personalWhiteParam = new PersonalWhiteListVO();
            setUserInfoToVO(personalWhiteParam);
            String currDt = TimeUtil.getCurrentDateTime();
            String currDt1 = currDt.substring(0,10);
            String currDt2 = currDt.substring(11);

            String userId = personalWhiteParam.getLoginUserId();
			String userName = queryUserName(userId);

			Iterator<PersonalWhiteExcelVO> iterator = personalWhiteExcelVO.iterator();
			while(iterator.hasNext()) {
				PersonalWhiteExcelVO tempExcelVO = iterator.next();
				PersonalWhiteListVO personalWhiteListVO = new PersonalWhiteListVO();
				//设置姓名
				personalWhiteListVO.setCusName(tempExcelVO.getCusName());
				//设置证件号码
				personalWhiteListVO.setCertCode(tempExcelVO.getCertCode());
				//设置企业名称
				personalWhiteListVO.setCompanyName(tempExcelVO.getCompanyName());
				//设置单位所在城市
				personalWhiteListVO.setCompanyCity(tempExcelVO.getCompanyCity());
				//设置职位
				personalWhiteListVO.setPositionPost(tempExcelVO.getPositionPost());
				//薪酬
				personalWhiteListVO.setSalary(tempExcelVO.getSalary());
				//上报机构
				personalWhiteListVO.setAppearOrg(tempExcelVO.getAppearOrg());

				//导入日期
				personalWhiteListVO.setImportDate(currDt1);
				//导入时间
				personalWhiteListVO.setImportTime(currDt2);
				//导入人员工号
				personalWhiteListVO.setImportEmpNo(userId);
				//导入人员名称
				personalWhiteListVO.setImportEmpName(userName);
				//最后更新日期
				personalWhiteListVO.setUpdateDate(currDt1);
				//最后更新时间
				personalWhiteListVO.setUpdateTime(currDt2);
				//最后更新人员
				personalWhiteListVO.setUpdateNo(userId);
				//最后更新人员名称
				personalWhiteListVO.setUpdateName(userName);

				list.add(personalWhiteListVO);
			}
		} else {
			throw new ExcelException("获取数据为空!");
		}
		return list;
	}

	private int execBatchInsertSql(List<PersonalWhiteListVO> inserListBatch) {
		int num = 0;
		return num = personalWhiteListService.batchInsertList(inserListBatch);
	}

	private String sortAndSpliceMap(Map<Integer, String> errorList) {
		String rs = "";
		//取出key值，根据key值排序
		Object[] key = errorList.keySet().toArray();
		Arrays.sort(key);
		//拼接信息
		Iterator ite = errorList.entrySet().iterator();
		while (ite.hasNext()) {
			Map.Entry string = (Map.Entry) ite.next();
			StringBuffer buffer = new StringBuffer();
			if (StringUtil.isNullorBank(rs)) {
				rs = (String) string.getValue();
			} else {
				rs = buffer.append(rs).append(",").append(string.getValue()).toString();
			}
		}
		return rs;
	}

	private void collError(Map<Integer, String> errorMap, Integer integer, String str) {
		if (errorMap.containsKey(integer)) {
			integer += 1;
			collError(errorMap,integer,str);
		} else {
			errorMap.put(integer,str);
		}
	}
	/**
	 * 根据用户号查用户名称
	 */
	public String queryUserName(String userId){
		String userName = "";
		userName = sUserService.queryUserNameByUserId(userId);
		return userName;
	}
	/****************************************导入更新结束**************************************************/

}
